package com.tengju.bff.interfaces.app.withdraw.facade;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.idanchuang.component.config.apollo.util.ConfigUtil;
import com.tengju.bff.domain.service.WithdrawService;
import com.tengju.bff.interfaces.app.withdraw.vo.*;
import com.tengju.bff.interfaces.covercharge.dto.BankInfo;
import com.tengju.bff.interfaces.covercharge.entity.dto.IdName;
import com.tengju.bff.interfaces.covercharge.entity.vo.ServiceLetaxRegisteredReturnResult;
import com.tengju.bff.interfaces.covercharge.service.IAttachmentService;
import com.tengju.bff.interfaces.covercharge.service.IServiceLetaxRegisteredService;
import com.tengju.bff.interfaces.covercharge.service.IServiceSignRecordService;
import com.tengju.bff.interfaces.covercharge.service.LeTaxOneService;
import com.tengju.bff.interfaces.shared.InterfaceException;
import com.tengju.bff.interfaces.shared.PhpAppResponse;
import com.tengju.settlement.domain.model.AchievementRepository;
import com.tengju.settlement.domain.model.AchievementStatus;
import com.tengju.settlement.domain.model.CardBinRepository;
import com.tengju.settlement.domain.model.GuideStatusRepository;
import com.tengju.settlement.domain.model.account.Account;
import com.tengju.settlement.domain.model.account.AccountRepository;
import com.tengju.settlement.domain.model.account.AccountType;
import com.tengju.settlement.domain.shared.Amount;
import com.tengju.user.application.login.SmsVerifyCodeService;
import com.tengju.user.application.user.UserInfoService;
import com.tengju.user.domain.model.archive.IdCardNo;
import com.tengju.user.domain.model.archive.letax.*;
import com.tengju.user.domain.model.archive.resume.BankCard;
import com.tengju.user.domain.model.archive.resume.BankCardId;
import com.tengju.user.domain.model.archive.resume.BankCardRepository;
import com.tengju.user.domain.model.archive.resume.BankCardStatus;
import com.tengju.user.domain.model.archive.sign.*;
import com.tengju.user.domain.model.article.ArticleInfoRepository;
import com.tengju.user.domain.model.login.UserType;
import com.tengju.user.domain.model.sms.OperationType;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.model.user.UserInfo;
import com.tengju.user.domain.model.user.UserInfoRepository;
import com.tengju.user.domain.service.HuaweiObsService;
import com.tengju.user.domain.shared.AccountId;
import com.tengju.user.domain.shared.BizException;
import com.tengju.user.domain.shared.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.tengju.bff.interfaces.shared.Formatter.beautyMoney;
import static com.tengju.user.domain.model.archive.letax.IdentityType.*;
import static com.tengju.user.domain.model.archive.letax.LetaxStatus.*;
import static com.tengju.user.domain.model.archive.sign.SelfCertificationStatus.TERMINATED;
import static com.tengju.user.domain.model.archive.sign.SelfCertificationType.ENTERPRISE;
import static com.tengju.user.domain.model.archive.sign.SelfCertificationType.PERSONAL;

@Slf4j
@Component
public class ServiceFeeFacade {

    private final UserInfoRepository userInfoRepository;

    private final AccountRepository accountRepository;

    private final AchievementRepository achievementRepository;

    private final SignRepository signRepository;

    private final SelfCertificationRepository selfCertificationRepository;

    private final BankCardRepository bankCardRepository;

    private final LetaxRepository letaxRepository;
    private final LetaxWhiteRepository letaxWhiteRepository;

    private final LetaxSnapshotRepository letaxSnapshotRepository;

    private final LetaxWithdrawRepository letaxWithdrawRepository;

    private final CardBinRepository cardBinRepository;

    private final WithdrawService withdrawService;

    private final BankServiceFacade bankServiceFacade;

    private final SignLogRepository signLogRepository;

    private final UserInfoService userInfoService;

    private final IServiceLetaxRegisteredService serviceLetaxRegisteredService;

    private final IServiceSignRecordService serviceSignRecordService;

    private final LeTaxOneService leTaxOneService;

    private final GuideStatusRepository guideStatusRepository;

    private final SmsVerifyCodeService smsVerifyCodeService;
    private final HuaweiObsService huaweiObsService;
    private final ArticleInfoRepository articleInfoRepository;
    private final SignRecordRepository signRecordRepository;
    private final IAttachmentService attachmentService;

    @Autowired
    public ServiceFeeFacade(UserInfoRepository userInfoRepository,
                            AccountRepository accountRepository,
                            AchievementRepository achievementRepository,
                            SignRepository signRepository,
                            SelfCertificationRepository selfCertificationRepository,
                            BankCardRepository bankCardRepository,
                            LetaxRepository letaxRepository,
                            LetaxSnapshotRepository letaxSnapshotRepository,
                            LetaxWithdrawRepository letaxWithdrawRepository,
                            CardBinRepository cardBinRepository,
                            WithdrawService withdrawService,
                            BankServiceFacade bankServiceFacade,
                            SignLogRepository signLogRepository,
                            HuaweiObsService huaweiObsService,
                            UserInfoService userInfoService,
                            IServiceLetaxRegisteredService serviceLetaxRegisteredService,
                            IServiceSignRecordService serviceSignRecordService, LeTaxOneService leTaxOneService,
                            GuideStatusRepository guideStatusRepository,
                            SmsVerifyCodeService smsVerifyCodeService,
                            ArticleInfoRepository articleInfoRepository,
                            LetaxWhiteRepository letaxWhiteRepository,
                            SignRecordRepository signRecordRepository,
                            IAttachmentService attachmentService) {
        this.userInfoRepository = userInfoRepository;
        this.accountRepository = accountRepository;
        this.achievementRepository = achievementRepository;
        this.signRepository = signRepository;
        this.selfCertificationRepository = selfCertificationRepository;
        this.bankCardRepository = bankCardRepository;
        this.letaxRepository = letaxRepository;
        this.letaxSnapshotRepository = letaxSnapshotRepository;
        this.letaxWithdrawRepository = letaxWithdrawRepository;
        this.cardBinRepository = cardBinRepository;
        this.withdrawService = withdrawService;
        this.bankServiceFacade = bankServiceFacade;
        this.signLogRepository = signLogRepository;
        this.userInfoService = userInfoService;
        this.serviceLetaxRegisteredService = serviceLetaxRegisteredService;
        this.serviceSignRecordService = serviceSignRecordService;
        this.leTaxOneService = leTaxOneService;
        this.guideStatusRepository = guideStatusRepository;
        this.smsVerifyCodeService = smsVerifyCodeService;
        this.huaweiObsService = huaweiObsService;
        this.articleInfoRepository = articleInfoRepository;
        this.letaxWhiteRepository = letaxWhiteRepository;
        this.signRecordRepository = signRecordRepository;
        this.attachmentService = attachmentService;
    }

    @Value("${withdrawal.service.fee.apply.popup}")
    private String serviceFeeApplyPopupMapString;

    public PhpAppResponse<ServiceFeeHomeVO> serviceFeeHome(
            com.tengju.settlement.domain.model.account.UserIdCode idCode) {
        ServiceFeeHomeVO.ServiceFeeHomeVOBuilder builder = ServiceFeeHomeVO.builder();
        Account account = accountRepository.findOrSave(idCode, AccountType.DATA_TREE);
        Amount preBalance = achievementRepository.sum(idCode, AchievementStatus.UNSETTLED);

        builder.balance(beautyMoney(account.getBalance()))
                .freezeBalance(beautyMoney(account.getFreezeBalance()))
                .preBalance(beautyMoney(preBalance))
                .isShowLetaxUpgradeFromDTtoTJ(1)
                .signFrom(SignFromEnum.SERVICE_PROVIDER.getCode());

        //身份判断 弹框处理
        Sign sign = signRepository.find(new UserIdCode(idCode.getValue()));
        String isSigned = "no";
        IdentityType currentIdentity = NO_IDENTITY;
        if (sign != null) {
            currentIdentity = sign.getHistoryIdentity() != null ?
                    sign.getHistoryIdentity() : sign.getCurrentIdentity();
            isSigned = sign.getIsSigned();
        }
        builder.currentIdentity(currentIdentity.getVal())
                .beforeIdentity(NO_IDENTITY.getVal())
                .isSigned(isSigned);

        //签约跳转弹框处理
        int layerStatus = 0;
        if ("no".equalsIgnoreCase(isSigned) && sign != null && sign.getHistoryIdentity() != null) {
            switch (sign.getHistoryIdentity()) {
                case NO_IDENTITY:
                    layerStatus = 1;
                    break;
                case PERSON:
                    layerStatus = 2;
                    break;
                case REGISTER_SOHO:
                    layerStatus = 3;
                    break;
                case CERTIFIED_INDIVIDUAL:
                    layerStatus = 4;
                    break;
                case CERTIFIED_BUSINESS:
                    layerStatus = 5;
                    break;
                default:
                    layerStatus = 0;
            }
        }

        //签约成功后提示框处理
        String remark = "";
        String bankNo = "";
        boolean updateLetaxStatus = false;
        if ("yes".equalsIgnoreCase(isSigned)) {
            //企业用户
            int checkStatus = 0;
            LetaxAccount letaxAccount = null;
            if (currentIdentity == CERTIFIED_BUSINESS
                    || currentIdentity == CERTIFIED_INDIVIDUAL) {
                SelfCertification selfCertification = selfCertificationRepository.findOne(
                        new UserIdCode(idCode.getValue()),
                        new AccountId(account.getAccountId().getValue()));
                bankNo = selfCertification.getBankNo();
                checkStatus = selfCertification.getStatus().getVal();
                remark = selfCertification.getRemark();
            } else if (currentIdentity == REGISTER_SOHO) {
                letaxAccount = letaxRepository.find(
                        new UserIdCode(idCode.getValue()),
                        new AccountId(account.getAccountId().getValue()));
                bankNo = letaxAccount.getBankNo();
                checkStatus = letaxAccount.getStatus().getVal();
                if (letaxAccount.getStatus() == NEED_AUTH) {
                    builder.isShowLetaxUpgradeFromDTtoTJ(0);
                }
                remark = letaxAccount.getRemark();
                updateLetaxStatus = LetaxStatus.inHand(letaxAccount.getStatus());
            } else if (currentIdentity == PERSON) {
                BankCard bankCard = bankCardRepository.find(
                        new UserIdCode(idCode.getValue()),
                        new AccountId(account.getAccountId().getValue()));
                bankNo = bankCard.getBankNo();
                checkStatus = 1;
            }

            //星际操作过的并且身份是在本月认证的
            int isCurrentMonth = 1;
            if (currentIdentity == CERTIFIED_BUSINESS || currentIdentity == CERTIFIED_INDIVIDUAL || currentIdentity == REGISTER_SOHO) {
                if (letaxAccount != null && letaxAccount.getCreateAt().toLocalDate().equals(LocalDate.now())) {
                    isCurrentMonth = 2;
                }
            }

            builder.status(checkStatus)
                    .remark(remark)
                    .isCurrentMonth(isCurrentMonth);

            String layerMsg = "";
            if (checkStatus == 1 && !"NOT_FIRST".equalsIgnoreCase(sign.getIsView())) {
                if (sign.getBeforeIdentity() != null &&
                        (sign.getBeforeIdentity() == PERSON
                                || sign.getBeforeIdentity() == REGISTER_SOHO)) {
                    layerStatus = 7;
                    layerMsg = "升级成功";
                } else {
                    if (currentIdentity == PERSON) {
                        layerStatus = 0;
                        layerMsg = "个人成功绑定";
                    } else {
                        layerStatus = 6;
                        layerMsg = "认证/注册成功";
                    }
                }
                sign.notFirst();
                signRepository.update(sign.getSignId(), sign);
            }
            builder.layerStatus(layerStatus)
                    .layerMsg(layerMsg);

            //注册用户弹框处理
            if (letaxAccount != null && sign.getCurrentIdentity() == REGISTER_SOHO
                    && (checkStatus == 2 || checkStatus == 6)) {
                if (checkStatus == 6) {
                    LetaxSnapshot snapshot = letaxSnapshotRepository
                            .find(letaxAccount.getLetaxAccountId());
                    if (snapshot.getRejectType() != null) {
                        // 2021-05-14 snapshot.getRejectType() == 06，但是不给registeredStatus赋值，导致app出现不了异常步骤
//                            && Set.of("01", "02", "03", "04", "05")
//                            .contains(snapshot.getRejectType())
                        builder.registeredStatus(snapshot.getRejectType())
                                .registeredMsg(snapshot.getRejectReason());
                    }
                } else {
                    builder.registeredStatus("06")
                            .registeredMsg(letaxAccount.getRemark());
                }
            }
            //获取银行卡信息
            if (StringUtils.isNotBlank(bankNo)) {
                bankNo = "***" + bankNo.substring(bankNo.length() - 4);
            }
            builder.bank(bankNo);
        } else {
            if (currentIdentity == CERTIFIED_BUSINESS || currentIdentity == CERTIFIED_INDIVIDUAL) {
                SelfCertification selfCertification = selfCertificationRepository.findOne(
                        new UserIdCode(idCode.getValue()),
                        new AccountId(account.getAccountId().getValue()));
                builder.status(selfCertification == null ? 0 : selfCertification.getStatus().getVal());
            } else if (currentIdentity == REGISTER_SOHO) {
                LetaxAccount letaxAccount = letaxRepository.find(
                        new UserIdCode(idCode.getValue()),
                        new AccountId(account.getAccountId().getValue()));
                builder.status(letaxAccount == null ? 0 : letaxAccount.getStatus().getVal());
                updateLetaxStatus = letaxAccount != null && LetaxStatus.inHand(letaxAccount.getStatus());
            } else if (currentIdentity == PERSON) {
                BankCard bankCard = bankCardRepository.find(
                        new UserIdCode(idCode.getValue()),
                        new AccountId(account.getAccountId().getValue()));
                if (bankCard.getStatus() == BankCardStatus.ENABLE) {
                    builder.status(1);
                } else if (bankCard.getStatus() == BankCardStatus.UNLINK) {
                    builder.status(2);
                }
            }

        }

        ServiceFeeHomeVO serviceFeeHomeVO = builder.build();

        if (serviceFeeHomeVO.getStatus() == 7) {
            serviceFeeHomeVO.setStatus(0);
        }

        //乐税授权中  异步去更新
        if (updateLetaxStatus) {
            new Thread(() -> this.updateRegisteredStatus(new com.tengju.settlement.domain.model.account.UserIdCode(idCode.getValue()))).start();
        }


        return PhpAppResponse.success(serviceFeeHomeVO);
    }

    public PhpAppResponse<PreBalanceVO> preBalance(
            com.tengju.settlement.domain.model.account.UserIdCode idCode) {

        PreBalanceVO.PreBalanceVOBuilder builder = PreBalanceVO.builder();

        //获取账户信息,没有就插入
        Account account = accountRepository.findOrSave(idCode, AccountType.DATA_TREE);
        Amount balance = account.getBalance();
        Amount freezeBalance = account.getFreezeBalance();

        LocalDate dateTen = LocalDate.now().withDayOfMonth(10);
        LocalDate nowTime = LocalDate.now();
        LocalDate month;
        if (nowTime.isAfter(dateTen)) {
            month = LocalDate.now();
        } else {
            month = dateTen.minusWeeks(2);
        }

        //获取市场补贴
        Amount achievementBalance = achievementRepository
                .sum(idCode, AchievementStatus.UNSETTLED, month);

        Amount allMoney = balance.add(freezeBalance).add(achievementBalance);

        //获取是否为白名单
        int countWhite = letaxWhiteRepository.countWhite(new UserIdCode(idCode.getValue()),
                new AccountId(account.getAccountId().getValue()));

        return PhpAppResponse.success(builder
                .allmoney(beautyMoney(allMoney))
                .whiteStatus(countWhite > 0 ? 1 : 0)
                .build());
    }

    public PhpAppResponse<GetCurrentDetailVO> getCurrentDetail(
            com.tengju.settlement.domain.model.account.UserIdCode idCode) {

        GetCurrentDetailVO data;

        Sign sign = signRepository.find(new UserIdCode(idCode.getValue()));
        if (sign != null && sign.getCurrentIdentity() != null
                && Set.of(REGISTER_SOHO, CERTIFIED_INDIVIDUAL, CERTIFIED_BUSINESS)
                .contains(sign.getCurrentIdentity())) {
            if (sign.getCurrentIdentity() == REGISTER_SOHO) {
                LetaxAccount letaxAccount = letaxRepository
                        .find(new UserIdCode(idCode.getValue()), LetaxStatus.TERMINATED);
                LetaxSnapshot snapshot = letaxSnapshotRepository
                        .find(letaxAccount.getLetaxAccountId());
                data = new GetCurrentDetailVO(
                        snapshot.getMerchantName(),
                        snapshot.getMerchantTaxNumber(),
                        snapshot.getName(),
                        snapshot.getIdCardNo(),
                        snapshot.getPhoneNumber()
                );
            } else {
                SelfCertificationType type =
                        sign.getCurrentIdentity() == CERTIFIED_INDIVIDUAL ? PERSONAL : ENTERPRISE;
                SelfCertification selfCertification = selfCertificationRepository
                        .find(new UserIdCode(idCode.getValue()), type, TERMINATED);
                Map<String, String> idCardJson = JsonUtil
                        .toMap(selfCertification.getIdCardImage());
                data = new GetCurrentDetailVO(
                        selfCertification.getIdCode().toString(),
                        selfCertification.getCompanyName(),
                        selfCertification.getCompanyAddress(),
                        selfCertification.getCompanyTel(),
                        selfCertification.getCompanyNo(),
                        selfCertification.getIdCardType(),
                        selfCertification.getIdCardName(),
                        selfCertification.getIdCardNo(),
                        selfCertification.getIdCardImage(),
                        selfCertification.getBankNo(),
                        selfCertification.getBankName(),
                        StringUtils.isNotBlank(selfCertification.getBusinessImg())
                                ? attachmentService.getUrl(selfCertification.getBusinessImg()) : "",
                        StringUtils.isNotBlank(selfCertification.getLicenceImg())
                                ? attachmentService.getUrl(selfCertification.getLicenceImg()) : "",
                        selfCertification.getType().getVal(),
                        selfCertification.getStatus().getVal(),
                        idCardJson != null ? idCardJson.get("up_image") : "",
                        idCardJson != null ? idCardJson.get("down_image") : "",
                        selfCertification.getLegalMobile()
                );
            }
        } else {
            return PhpAppResponse.paramError();
        }
        return PhpAppResponse.success(data);
    }

    public Boolean setGuideStatus(
            com.tengju.settlement.domain.model.account.UserIdCode userIdCode) {

        return guideStatusRepository.setGuideStatus(userIdCode);

    }


    public PhpAppResponse<Object> withdrawalLogStatus(
            com.tengju.settlement.domain.model.account.UserIdCode idCode) {

        Account account = accountRepository.find(idCode, AccountType.DATA_TREE);

        if (account == null) {
            return PhpAppResponse.error("用户账号不存在");
        }

        int withdrawCount = letaxWithdrawRepository.count(new UserIdCode(idCode.getValue()),
                new AccountId(account.getAccountId().getValue()),
                List.of(LetaxWithdrawStatus.INIT, LetaxWithdrawStatus.APPLIED),
                REGISTER_SOHO);

        return PhpAppResponse.success(new Object() {
            int status = withdrawCount > 0 ? 2 : 1;
            String mobile = account.getMobile();
        });
    }

//
//    public PhpAppResponse<Boolean> personalWithdrawalCertification(
//            com.tengju.settlement.domain.model.account.UserIdCode idCode,
//            CertificationRequest request) throws InterfaceException {
//
//        if (StringUtils.isEmpty(request.getIdCardName()) || StringUtils
//                .isEmpty(request.getIdCardNo()) ||
//                StringUtils.isEmpty(request.getCardNo())) {
//            return PhpAppResponse.paramError();
//        }
//
//        String idCardName = request.getIdCardName();
//        IdCardNo idCardNo = new IdCardNo(request.getIdCardNo());
//        String bankNo = request.getCardNo().strip();
//        String bankName = cardBinRepository.getBankName(bankNo);
//
//        //验证手机号码 个人签约(新增收款账户)
//        PhpAppResponse<Boolean> error = certificationCheck(idCode, request,
//                OperationType.PERSONAL_SIGN);
//        if (error != null) {
//            return error;
//        }
//
//        //判断是否存在恶意点击
//        PhpAppResponse<Boolean> duplicateError = duplicateApplyCheck(idCode);
//        if (duplicateError != null) {
//            return duplicateError;
//        }
//
//        Account account = accountRepository.find(idCode, AccountType.DATA_TREE);
//
//        Sign sign = signRepository.find(new UserIdCode(idCode.getValue()));
//        boolean history = false;
//        if (sign == null) {
//            BankCard bankCard = bankCardRepository.find(new UserIdCode(idCode.getValue()),
//                    BankCardStatus.ENABLE,
//                    new AccountId(account.getAccountId().getValue())
//            );
//            if (bankCard != null) {
//                return PhpAppResponse.error(8008, "您已经申请过");
//            }
//            //默认收款账户中
//            BankCard idCardBankCard = bankCardRepository.find(idCardNo, BankCardStatus.ENABLE);
//            if (idCardBankCard != null && idCardBankCard.getIdCode().getValue() != idCode
//                    .getValue()) {
//                return PhpAppResponse.error(8008, "该身份证号已被使用了");
//            }
//        } else {
//            if (sign.getHistoryIdentity() == PERSON) {
//                if ((sign.getCurrentIdentity() != PERSON) || !Objects
//                        .equals(sign.getIsSigned(), "no")) {
//                    return PhpAppResponse.error(8008, "您当前身份无法继续进行申请.");
//                }
//                history = true;
//            } else {
//                if (sign.getCurrentIdentity() != NO_IDENTITY) {
//                    return PhpAppResponse.error(8008, "您当前身份无法继续进行申请.");
//                }
//
//                BankCard bankCard = bankCardRepository.find(new UserIdCode(idCode.getValue()),
//                        BankCardStatus.ENABLE,
//                        new AccountId(account.getAccountId().getValue())
//                );
//                if (bankCard != null) {
//                    return PhpAppResponse.error(8008, "您已经申请过");
//                }
//                //默认收款账户中
//                BankCard idCardBankCard = bankCardRepository.find(idCardNo, BankCardStatus.ENABLE);
//                if (idCardBankCard != null && idCardBankCard.getIdCode().getValue() != idCode
//                        .getValue()) {
//                    return PhpAppResponse.error(8008, "该身份证号已被使用了");
//                }
//            }
//        }
//        if (!(bankNo.matches("^\\d+$"))) {
//            return PhpAppResponse.paramError("银行卡格式有误，请检查是否包含空格或除数字以外的其它字符");
//        }
//
//        LetaxAccount letaxAccount = letaxRepository
//                .findByIdCardNoAndNotStatus(idCardNo, LetaxStatus.TERMINATED);
//        if (letaxAccount != null
//                && letaxAccount.getUserIdCode().getValue() != idCode.getValue()) {
//            return PhpAppResponse.error(8008, "该身份证号已被使用了");
//        }
//
//        // 第三方银行卡身份校验
//        try {
//            userInfoService.checkBankIdCard(idCardName, bankNo, idCardNo.getValue());
//        } catch (Exception e) {
//            return PhpAppResponse.error(8008, e.getMessage());
//        }
//
//        BankCard bankCard = new BankCard(
//                null,
//                new AccountId(account.getAccountId().getValue()),
//                new UserIdCode(idCode.getValue()),
//                idCardNo,
//                idCardName,
//                bankNo,
//                bankName,
//                BankCardStatus.ENABLE
//        );
//
//        try {
//            bankServiceFacade.sign(new UserIdCode(idCode.getValue()), bankCard, sign, history);
//        } catch (Exception e) {
//            log.error("用户个人认证报错:", e);
//            return PhpAppResponse.error(8008, "个人签约认证失败,请联系管家获取帮助");
//        }
//        return PhpAppResponse.success(true);
//    }


//    public PhpAppResponse<Boolean> individualContractIdCheckWhetherThereIsAny(
//            com.tengju.settlement.domain.model.account.UserIdCode idCode,
//            CertificationRequest request) throws InterfaceException {
//        if (StringUtils.isEmpty(request.getIdCardName()) || StringUtils
//                .isEmpty(request.getIdCardNo()) ||
//                StringUtils.isEmpty(request.getCardNo())) {
//            return PhpAppResponse.paramError();
//        }
//        String idCardName = request.getIdCardName();
//        IdCardNo idCardNo = new IdCardNo(request.getIdCardNo());
//        String bankNo = request.getCardNo().strip();
//
//        // 验证手机号码 个人身份验证
//        PhpAppResponse<Boolean> error = certificationCheck(idCode, request,
//                OperationType.PERSONAL_AUTH);
//        if (error != null) {
//            return error;
//        }
//
//        BankCard idCardBankCard = bankCardRepository.find(idCardNo, BankCardStatus.ENABLE);
//        if (idCardBankCard.getIdCode().getValue() != idCode.getValue()) {
//            return PhpAppResponse.error(8008, "该身份证号已被使用了");
//        }
//
//        LetaxAccount letaxAccount = letaxRepository
//                .findByIdCardNoAndNotStatus(idCardNo, LetaxStatus.TERMINATED);
//        if (letaxAccount != null
//                && letaxAccount.getUserIdCode().getValue() != idCode.getValue()) {
//            return PhpAppResponse.error(8008, "该身份证号已被使用了");
//        }
//
//        // 第三方银行卡身份校验
//        try {
//            userInfoService.checkBankIdCard(idCardName, bankNo, idCardNo.getValue());
//        } catch (Exception e) {
//            return PhpAppResponse.error(8008, e.getMessage());
//        }
//
//        return PhpAppResponse.success(true);
//
//    }

//
//    public PhpAppResponse<Boolean> editPersonBankInfo(
//            com.tengju.settlement.domain.model.account.UserIdCode idCode,
//            WithdrawRequest request) {
//        try {
//
//            if (StringUtils.isEmpty(request.getIdCardName()) || StringUtils
//                    .isEmpty(request.getIdCardNo()) ||
//                    StringUtils.isEmpty(request.getCardNo())) {
//                return PhpAppResponse.paramError();
//            }
//            BankCardId bankCardId = request.getId() == 0 ? null : new BankCardId(request.getId());
//            String idCardName = request.getIdCardName();
//            IdCardNo idCardNo = new IdCardNo(request.getIdCardNo());
//            String bankNo = request.getCardNo().strip();
//            String withdrawLogId = request.getWithdrawLogId();
//            String bankName = cardBinRepository.getBankName(bankNo);
//
//            //验证手机号码 修改收款账户
//            PhpAppResponse<Boolean> error = certificationCheck(idCode, request,
//                    OperationType.MODIFY_ACCOUNT);
//            if (error != null) {
//                return error;
//            }
//
//            if (StringUtils.isBlank(withdrawLogId)) {
//                if (bankCardId == null) {
//                    return PhpAppResponse.paramError();
//                }
//
//                return modifyPersonBankInfo(bankCardId, idCode, idCardName, idCardNo, bankNo,
//                        bankName,
//                        withdrawLogId);
//
//            } else {
//                return modifyPersonalWithdrawalRecordCard(bankCardId, idCode, idCardName, idCardNo,
//                        bankNo,
//                        bankName, withdrawLogId);
//            }
//        } catch (Exception e) {
//
//            return PhpAppResponse.error(e.getMessage());
//        }
//    }

    private PhpAppResponse<Boolean> modifyPersonalWithdrawalRecordCard(BankCardId bankCardId,
                                                                       com.tengju.settlement.domain.model.account.UserIdCode idCode,
                                                                       String idCardName, IdCardNo idCardNo,
                                                                       String bankNo, String bankName,
                                                                       String withdrawLogId) {

        if (!(bankNo.matches("^\\d+$"))) {
            return PhpAppResponse.paramError("银行卡格式有误，请检查是否包含空格或除数字以外的其它字符");
        }

        //判断是否存在恶意点击
        PhpAppResponse<Boolean> duplicateError = duplicateApplyCheck(idCode);
        if (duplicateError != null) {
            return duplicateError;
        }

        LetaxAccount letaxAccount = letaxRepository
                .findByIdCardNoAndNotStatus(idCardNo, LetaxStatus.TERMINATED);
        if (letaxAccount != null
                && letaxAccount.getUserIdCode().getValue() != idCode.getValue()) {
            return PhpAppResponse.error(8008, "该身份证号已被使用了");
        }

        //默认收款账户中
        BankCard idCardBankCard = bankCardRepository.find(idCardNo, BankCardStatus.ENABLE);
        if (idCardBankCard != null && idCardBankCard.getIdCode().getValue() != idCode.getValue()) {
            return PhpAppResponse.error(8008, "该身份证号在默认收款账户中被使用了");
        }

        // 第三方银行卡身份校验
        try {
            userInfoService.checkBankIdCard(idCardName, bankNo, idCardNo.getValue());
        } catch (Exception e) {
            return PhpAppResponse.error(8008, e.getMessage());
        }

        bankServiceFacade
                .bankWithdraw(new UserIdCode(idCode.getValue()), idCardNo, idCardName, bankNo,
                        bankName, withdrawLogId);

        return null;
    }

    /**
     * 修改个人签约的收款账户信息
     */
    private PhpAppResponse<Boolean> modifyPersonBankInfo(BankCardId bankCardId,
                                                         com.tengju.settlement.domain.model.account.UserIdCode idCode,
                                                         String idCardName, IdCardNo idCardNo, String bankNo,
                                                         String bankName, String withdrawLogId) {
        try {

            //判断是否存在恶意点击
            PhpAppResponse<Boolean> duplicateError = duplicateApplyCheck(idCode);
            if (duplicateError != null) {
                return duplicateError;
            }

            Account account = accountRepository.findOrSave(idCode, AccountType.DATA_TREE);

            BankCard bankCard = bankCardRepository.find(bankCardId,
                    BankCardStatus.ENABLE,
                    new AccountId(account.getAccountId().getValue()));
            if (bankCard == null) {
                return PhpAppResponse.error(8010, "银行账户信息不存在");
            }

            if (!bankCard.getIdCode().sameValueAs(new UserIdCode(idCode.getValue()))) {
                return PhpAppResponse.paramError("银行账户信息所属人不一致");
            }

            if (!(bankNo.matches("^\\d+$"))) {
                return PhpAppResponse.paramError("银行卡格式有误，请检查是否包含空格或除数字以外的其它字符");
            }

            Sign sign = signRepository.find(new UserIdCode(idCode.getValue()));

            if (withdrawLogId == null) {
                if (sign.getCurrentIdentity() != PERSON) {
                    return PhpAppResponse.paramError("当前不是个人签约状态");
                }
                if (!"yes".equalsIgnoreCase(sign.getIsSigned())) {
                    return PhpAppResponse.paramError("当前没有进行签约");
                }
            }

            LetaxAccount letaxAccount = letaxRepository
                    .findByIdCardNoAndNotStatus(idCardNo, LetaxStatus.TERMINATED);
            if (letaxAccount != null
                    && letaxAccount.getUserIdCode().getValue() != idCode.getValue()) {
                return PhpAppResponse.error(8008, "该身份证号已被使用了");
            }

            //默认收款账户中
            BankCard idCardBankCard = bankCardRepository.find(idCardNo, BankCardStatus.ENABLE);
            if (idCardBankCard != null && idCardBankCard.getIdCode().getValue() != idCode
                    .getValue()) {
                return PhpAppResponse.error(8008, "该身份证号在默认收款账户中被使用了");
            }

            // 第三方银行卡身份校验
            try {
                userInfoService.checkBankIdCard(idCardName, bankNo, idCardNo.getValue());
            } catch (Exception e) {
                return PhpAppResponse.error(8008, e.getMessage());
            }

            bankServiceFacade.bankWithdraw(new UserIdCode(idCode.getValue()), account,
                    idCardNo, idCardName, bankNo, bankName);

            return PhpAppResponse.success(true);
        } catch (Exception e) {
            log.error("修改个人签约服务费提现收款账户时报错", e);
            return PhpAppResponse.error(e.getMessage());
        }
    }


    private PhpAppResponse<Boolean> duplicateApplyCheck(
            com.tengju.settlement.domain.model.account.UserIdCode
                    idCode) {
        //判断是否存在恶意点击
        if (withdrawService.isPersonalAuthClick(
                new com.tengju.bff.domain.shared.UserIdCode(idCode.getValue()))) {
            return PhpAppResponse.paramError("您已经申请过，请不要重复点击！");
        } else {
            withdrawService.personalAuthClick(
                    new com.tengju.bff.domain.shared.UserIdCode(idCode.getValue()));
        }
        return null;
    }
//
//    private PhpAppResponse<Boolean> certificationCheck(
//            com.tengju.settlement.domain.model.account.UserIdCode idCode,
//            CertificationRequest request, OperationType type) throws InterfaceException {
//        IdCardNo idCardNo = new IdCardNo(request.getIdCardNo());
//
//        if (!idCardNo.isValid()) {
//            return PhpAppResponse.paramError("身份证信息填写错误，请检查后提交");
//        }
//        //判断年龄是否超过18岁
//        if (idCardNo.getAgeByID() < 18) {
//            return PhpAppResponse.paramError("您当前提交的信息显示年龄未满18周岁，本平台仅限年满18周岁以上的人员合作，请更换绑定信息");
//        }
//
//        //验证手机号码---统一调用
//        UserInfo userInfo = userInfoRepository.getByIdCode(new UserIdCode(idCode.getValue()));
//        if (userInfo == null) {
//            return PhpAppResponse.paramError("用户不存在");
//        }
//        String verifyCode = request.getVerifyCode();
//        boolean result = smsVerifyCodeService.
//                checkVerifyCode(UserType.USER, type, userInfo.getAreaCode(), userInfo.getMobile(),
//                        verifyCode);
//
//        if (!result) {
//            return PhpAppResponse.paramError("验证码错误！");
//        }
//
//        return null;
//    }

    public PhpAppResponse<BankVO> getBankInfo(
            com.tengju.settlement.domain.model.account.UserIdCode idCode,
            IdentityType identity) {
        try {

            Sign sign = signRepository.find(new UserIdCode(idCode.getValue()));
            IdentityType currentIdentityType =
                    identity == null ? sign.getCurrentIdentity() : identity;
            BankVO bankVO = null;
            switch (currentIdentityType) {
                case PERSON:
                    BankCard bankCard = bankCardRepository
                            .findLastOne(new UserIdCode(idCode.getValue()),
                                    BankCardStatus.ENABLE);
                    if (bankCard != null) {
                        bankVO = new BankVO(
                                bankCard.getBankCardId().toString(),
                                bankCard.getBankNo(),
                                bankCard.getBankName(),
                                bankCard.getIdCardNo().toString(),
                                bankCard.getIdCardName());
                    }
                    break;
                case REGISTER_SOHO:
                    LetaxAccount letaxAccount = letaxRepository
                            .find(new UserIdCode(idCode.getValue()),
                                    LetaxStatus.TERMINATED);
                    bankVO = new BankVO(
                            letaxAccount.getLetaxAccountId().toString(),
                            letaxAccount.getBankNo(),
                            letaxAccount.getBankName(),
                            letaxAccount.getIdCardNo(),
                            letaxAccount.getIdCardName()
                    );
                    break;
                case CERTIFIED_BUSINESS:
                    SelfCertification business = selfCertificationRepository
                            .find(new UserIdCode(idCode.getValue()), ENTERPRISE, TERMINATED);
                    bankVO = new BankVO(
                            business.getSelfCertificationId().toString(),
                            business.getBankNo(),
                            business.getBankName(),
                            business.getIdCardNo(),
                            business.getIdCardName()
                    );
                    break;
                case CERTIFIED_INDIVIDUAL:
                    SelfCertification personal = selfCertificationRepository
                            .find(new UserIdCode(idCode.getValue()), PERSONAL, TERMINATED);
                    bankVO = new BankVO(
                            personal.getSelfCertificationId().toString(),
                            personal.getBankNo(),
                            personal.getBankName(),
                            personal.getIdCardNo(),
                            personal.getIdCardName()
                    );
                    break;
            }

            return PhpAppResponse.success(bankVO);
        } catch (Exception e) {
            log.error("查看是否有收款账户信息失败", e);
            return PhpAppResponse.error(e.getMessage());
        }
    }


    public PhpAppResponse<RegisterPhoneVO> registeredPhone(
            com.tengju.settlement.domain.model.account.UserIdCode idCode) {
        UserInfo user = userInfoRepository.getByIdCode(new UserIdCode(idCode.getValue()));
        if (user != null && user.getMobile() != null) {
            return PhpAppResponse
                    .success(new RegisterPhoneVO(user.getAreaCode(), user.getMobile()));
        } else {
            return PhpAppResponse.error("查看失败，稍后再来");
        }
    }

    @Transactional
    public PhpAppResponse<Boolean> addRegisteredCheck(
            com.tengju.settlement.domain.model.account.UserIdCode idCode,
            CertificationRequest request) {
        if (StringUtils.isEmpty(request.getIdCardName())
                || StringUtils.isEmpty(request.getIdCardNo())) {
            return PhpAppResponse.paramError();
        }

        //判断是否存在恶意点击
        if (withdrawService.isRegisteredCheckClick(
                new com.tengju.bff.domain.shared.UserIdCode(idCode.getValue()))) {
            return PhpAppResponse.paramError("请不要连续操作，10秒后再来！");
        } else {
            withdrawService.registeredCheckClick(
                    new com.tengju.bff.domain.shared.UserIdCode(idCode.getValue()));
        }

        IdCardNo idCardNo = new IdCardNo(request.getIdCardNo());
        String idCardName = request.getIdCardName().strip();

        Account account = accountRepository.findOrSave(idCode, AccountType.DATA_TREE);

        LetaxAccount letaxAccount = letaxRepository.find(new UserIdCode(idCode.getValue()),
                new AccountId(account.getAccountId().getValue()));
        if (letaxAccount != null
                && !letaxAccount.isTerminated()
                && RELATE_FAILED != letaxAccount.getStatus()
                && REGISTER_FAILED != letaxAccount.getStatus()) {
            throw new BizException("该用户已经有了个体户收款账户信息");
        }

        // 不同的账号使用不同的身份证
        BankCard bankCard = bankCardRepository.find(idCardNo, BankCardStatus.ENABLE);
        if (bankCard != null && bankCard.getIdCode().getValue() != idCode.getValue()) {
            throw new BizException("身份证已被其他个人账号使用，请更换");
        }

        // 注册信息表中
        LetaxAccount exist = letaxRepository
                .findByIdCardNoAndNotStatus(idCardNo, LetaxStatus.TERMINATED);
        if (exist != null && exist.getUserIdCode().getValue() != idCode.getValue()) {
            throw new BizException("身份证已关联其他个体户，请更换");
        }

        // 第三方银行卡身份校验
        try {
            userInfoService.checkUserInfoForSign(idCardName, idCardNo.getValue());
        } catch (Exception e) {
            return PhpAppResponse.error(8008, e.getMessage());
        }

        return PhpAppResponse.success(true);
    }

    @Transactional
    public PhpAppResponse<Long> newAddRegistered(
            com.tengju.settlement.domain.model.account.UserIdCode idCode,
            RegisterRequest request) {
        if (StringUtils.isEmpty(request.getIdCardName())
                || StringUtils.isEmpty(request.getIdCardNo())) {
            return PhpAppResponse.paramError();
        }

        //判断是否存在恶意点击
        if (withdrawService.isAddRegisteredCheckClick(
                new com.tengju.bff.domain.shared.UserIdCode(idCode.getValue()))) {
            return PhpAppResponse.paramError("请不要连续操作，10秒后再来！");
        } else {
            withdrawService.addRegisteredCheckClick(
                    new com.tengju.bff.domain.shared.UserIdCode(idCode.getValue()));
        }
        IdCardNo idCardNo = new IdCardNo(request.getIdCardNo());
        String idCardName = request.getIdCardName().strip();
        String bankNo = "";
        String bankName = cardBinRepository.getBankName(bankNo);
        Integer fromType = request.getFromType();

        // 验证手机号码 注册乐税个体户
        UserInfo userInfo = userInfoRepository.getByIdCode(new UserIdCode(idCode.getValue()));
        if (userInfo == null) {
            return PhpAppResponse.paramError("用户不存在！");
        }

        //获取账户信息
        Account account = accountRepository.findOrSave(idCode, AccountType.DATA_TREE);

        LetaxAccount letaxAccount = letaxRepository.findOne(new UserIdCode(idCode.getValue()),
                new AccountId(account.getAccountId().getValue()), LetaxStatus.TERMINATED);
        if (letaxAccount == null) {
            PhpAppResponse<PreBalanceVO> preBalance = preBalance(idCode);
            if (preBalance.getCode() != 0) {
                throw new BizException("尚未注册个体户条件，可选择其他身份");
            }
        }

        leTaxOneService.idcardAndBank(idCode, idCardNo, idCardName, bankNo);

        //是否是更新数据
        boolean updateStatus = false;
        boolean registeredStatus = false;

        //签约信息处理
        Sign existSign = signRepository.find(new UserIdCode(idCode.getValue()));
        String isSigned = existSign != null ? existSign.getIsSigned() : "no";
        SignId signId = null;

        if (request.getRegisteredType() == 1) {//新用户注册或者更新
            if (existSign != null) {
                boolean needUpdate = false;
                if (existSign.getHistoryIdentity() != null) {
                    existSign.change(null);
                    needUpdate = true;
                }
                if (existSign.getCurrentIdentity() != REGISTER_SOHO) {
                    existSign.change(existSign.getCurrentIdentity(), REGISTER_SOHO);
                    needUpdate = true;
                }
                if (!"yes".equalsIgnoreCase(isSigned)) {
                    existSign.changeIsSigned();
                    needUpdate = true;
                }
                if (needUpdate) {
                    signRepository.update(existSign.getSignId(), existSign);
                }
                signId = existSign.getSignId();
            } else {
                Sign sign = new Sign(
                        null,
                        new UserIdCode(idCode.getValue()),
                        NO_IDENTITY,
                        REGISTER_SOHO,
                        null,
                        "yes",
                        "FIRST",
                        LocalDateTime.now(),
                        null
                );
                signId = new SignId(signRepository.save(sign));
            }
        } else {//老用户升级
            if (existSign == null) {
                throw new BizException("该用户没有签约信息");
            }
            if (existSign.getCurrentIdentity() != PERSON) {
                throw new BizException("该用户升级前身份不是个人");
            }
            //更新身份
            IdentityType beforeIdentity = PERSON;
            existSign.changeSign2Yes(beforeIdentity, REGISTER_SOHO, null, "FIRST");
            signRepository.update(existSign.getSignId(), existSign);
            SignLog signLog = new SignLog(
                    new UserIdCode(idCode.getValue()),
                    "升级",
                    beforeIdentity,
                    REGISTER_SOHO,
                    idCode.toString()
            );
            signLogRepository.save(signLog);

            //解绑个人信息
            bankCardRepository.update(new UserIdCode(idCode.getValue()),
                    BankCardStatus.ENABLE,
                    BankCardStatus.UNLINK);

            signId = existSign.getSignId();
        }

        LetaxAccountId letaxAccountId;
        if (letaxAccount != null) {//更新
            int withdrawCount = letaxWithdrawRepository.count(new UserIdCode(idCode.getValue()),
                    new AccountId(account.getAccountId().getValue()),
                    List.of(LetaxWithdrawStatus.INIT, LetaxWithdrawStatus.APPLIED),
                    REGISTER_SOHO);
            if ("yes".equalsIgnoreCase(isSigned)
                    && !(2 == fromType && letaxAccount.getStatus() == FINISHED)
                    && withdrawCount > 0) {
                throw new BizException("该账户有待审核的记录，无法编辑");
            }

            //用户升级
            if (letaxAccount.getStatus() != FINISHED) {
                registeredStatus = true;
            }

            letaxAccount.bindBank(bankNo, bankName);
            letaxAccount.check();

            // 判断刷脸状态和关联失败是可以修改的
            ServiceLetaxRegisteredReturnResult merchantInfo = serviceLetaxRegisteredService
                    .getMerchantInfo(((Long) idCode.getValue()).intValue());
            if ((merchantInfo != null && "N".equalsIgnoreCase(merchantInfo.getIfFaceAuthenticate()))
                    || letaxAccount.getStatus() == RELATE_FAILED) {
                letaxAccount.bindIdCard(idCardNo.toString(), idCardName);
            } else {
                if (!letaxAccount.getIdCardNo().equalsIgnoreCase(idCardNo.toString())) {
                    throw new BizException("您已经完成刷脸状态不能修改身份证");
                }
                if (!letaxAccount.getIdCardName().equalsIgnoreCase(idCardName)) {
                    throw new BizException("您已经完成刷脸状态不能修改身份证");
                }
            }

            LetaxSnapshot snapshot = letaxSnapshotRepository.find(letaxAccount.getLetaxAccountId());
            if (snapshot != null) {
                if (StringUtils.isNotEmpty(snapshot.getIdCardNo())
                        && !snapshot.getIdCardNo().equalsIgnoreCase(idCardNo.getValue())) {
                    log.error("注册乐税个体户身份证：" + snapshot.getIdCardNo() +
                            "----" + idCardNo.getValue() +
                            "----" + JsonUtil.toJSONString(snapshot));
                    throw new BizException("身份证号与乐税注册法人身份证信息不一致");
                }
                if ("00".equalsIgnoreCase(snapshot.getStateCode())) {//只有是成功才更新状态
                    letaxAccount.finish();
                    updateStatus = true;
                }
            }

            //更新注册信息
            letaxRepository.update(letaxAccount.getLetaxAccountId(), letaxAccount);
            letaxAccountId = letaxAccount.getLetaxAccountId();
        } else {//注册
            //插入注册表
            LetaxAccount newLetaxAccount = new LetaxAccount(
                    null,
                    new UserIdCode(idCode.getValue()),
                    new AccountId(account.getAccountId().getValue()),
                    bankNo,
                    bankName,
                    idCardNo.toString(),
                    idCardName,
                    "",
                    LetaxStatus.UN_APPLY,
                    null,
                    null
            );
            long save = letaxRepository.save(newLetaxAccount);
            letaxAccountId = new LetaxAccountId(save); //验证插入后id返回
        }

        SignRecord record = new SignRecord(signId, SignFromEnum.form(fromType));
        signRecordRepository.insertSelective(record);

        Sign sign = signRepository.find(new UserIdCode(idCode.getValue()));
        //只要在星际提交过信息且身份是成功的，且没有通知会员，就去通知会员，同时申请证书
        //SignRecord signRecord = signRecordRepository.findOrderBy(sign.getSignId());
        if (((letaxAccount != null && letaxAccount.getStatus() == FINISHED) || updateStatus)
                && sign.getCurrentIdentity() == REGISTER_SOHO && sign.getNoticeStatus() == 0) {
            leTaxOneService.signSuccessToNoticeMember(idCode, letaxAccount.getCheckTime(), sign);
        }

        //只有初次升级且个体户身份证成功后才能调用java
        if ((existSign != null && existSign.getBeforeIdentity() == PERSON
                && existSign.getCurrentIdentity() == REGISTER_SOHO && updateStatus
                && registeredStatus)) {
            // 调用java修改收款账户信息
            try {
                leTaxOneService.modifyRegisteredWithdrawalRecords(idCode, PERSON);
            } catch (Exception e) {
                log.error("modifyRegisteredWithdrawalRecords error", e);
                return PhpAppResponse.error("系统有点累，请稍后再试");
            }
        }
        return PhpAppResponse.success(letaxAccountId.getValue());
    }

    public PhpAppResponse<RegisteredInfoVO> registeredInfo(
            com.tengju.settlement.domain.model.account.UserIdCode idCode) {
        RegisteredInfoVO infoVO = null;
        Account account = accountRepository.findOrSave(idCode, AccountType.DATA_TREE);
        LetaxAccount letaxAccount = letaxRepository
                .findOneByStatus(new UserIdCode(idCode.getValue()),
                        new AccountId(account.getAccountId().getValue()), FINISHED);
        if (letaxAccount == null) {
            letaxAccount = letaxRepository.findOneNotIn(new UserIdCode(idCode.getValue()),
                    new AccountId(account.getAccountId().getValue()),
                    List.of(LetaxStatus.FINISHED, LetaxStatus.RELATE_FAILED,
                            LetaxStatus.TERMINATED));
        }
        if (letaxAccount != null) {
            LetaxSnapshot letaxSnapshot = letaxSnapshotRepository
                    .find(letaxAccount.getLetaxAccountId());
            infoVO = letaxSnapshot == null ? null :
                    new RegisteredInfoVO(
                            letaxSnapshot.getLetaxSnapshotId().toString(),
                            letaxSnapshot.getMerchantName(),
                            letaxSnapshot.getName(),
                            letaxSnapshot.getIdCardNo(),
                            letaxSnapshot.getPhoneNumber(),
                            letaxSnapshot.getMerchantTaxNumber());
        }
        return PhpAppResponse.success(infoVO);
    }

    @Transactional
    public PhpAppResponse<Boolean> updateRegisteredStatus(
            com.tengju.settlement.domain.model.account.UserIdCode idCode) {
        Account account = accountRepository.find(idCode, AccountType.DATA_TREE);
        if (account == null) {
            return PhpAppResponse.paramError("请求失败，该商户没有注册服务费账户");
        }
        //判断注册用户是否存在
        LetaxAccount letaxAccount = letaxRepository.find(new UserIdCode(idCode.getValue()),
                new AccountId(account.getAccountId().getValue()));
        if (letaxAccount == null || letaxAccount.getStatus() == LetaxStatus.TERMINATED) {
            return PhpAppResponse.paramError("请求失败，该商户没有个体户信息");
        }

        //获取签约记录信息
        UserIdCode userIdCode = new UserIdCode(idCode.getValue());
        Sign serviceInfos = signRepository.find(userIdCode);
        if (serviceInfos == null) {
            return PhpAppResponse.paramError("请求失败，该商户没有进行签约");
        }

        // 请求第三方信息
        ServiceLetaxRegisteredReturnResult merchantInfo = serviceLetaxRegisteredService
                .getMerchantInfo((int) idCode.getValue());
        if (merchantInfo != null) {
            LetaxSnapshotId letaxSnapshotId;
            LetaxSnapshot letaxSnapshot = convert(userIdCode, letaxAccount.getLetaxAccountId(),
                    merchantInfo);
            LetaxSnapshot existSnapshot = letaxSnapshotRepository
                    .find(letaxAccount.getLetaxAccountId());
            if (existSnapshot != null) {//更新
                letaxSnapshotRepository.update(existSnapshot.getLetaxSnapshotId(), letaxSnapshot);
                letaxSnapshotId = existSnapshot.getLetaxSnapshotId();
            } else {//新增
                letaxSnapshotRepository.save(letaxSnapshot);
                letaxSnapshotId = letaxSnapshot.getLetaxSnapshotId();
            }

            if (letaxSnapshotId != null) {
                LetaxStatus updateStatus = null;
                String updateRemark = null;
                IdentityType updateHistoryIdentity = null;
                String updateIsSigned = "yes";
                String updateIsView = "NOT_FIRST";

                String stateCode = letaxSnapshot.getStateCode();
                if (StringUtils.isNotEmpty(stateCode)) {
                    switch (stateCode) {
                        case "00"://正常
                            if (StringUtils.isEmpty(letaxSnapshot.getIdCardNo())) {//身份证为空
                                //另一个平台乐税有返回信息且税号相同且有返回法人身份证
                                if (existSnapshot != null
                                        && !Set.of(FINISHED, RELATE_FAILED)
                                        .contains(letaxAccount.getStatus())
                                        && letaxSnapshot.getMerchantTaxNumber()
                                        .equalsIgnoreCase(existSnapshot.getMerchantTaxNumber())
                                        && StringUtils.isNotEmpty(existSnapshot.getIdCardNo())) {
                                    letaxSnapshot.updateIdCardNo(existSnapshot.getIdCardNo());
                                }
                            }
                            //身份证匹配信息
                            if (StringUtils.isNotEmpty(letaxSnapshot.getIdCardNo())
                                    && letaxAccount.getIdCardNo()
                                    .equalsIgnoreCase(letaxSnapshot.getIdCardNo())) {
                                updateStatus = FINISHED;//注册完成
                            } else {
                                updateStatus = RELATE_FAILED;//关联失败
                                updateRemark = "收款账户信息与注册个体户工商法人信息不一致，请修改收款账户信息";
                            }
                            break;
                        case "01"://申请中
                            updateStatus = APPLIED;//申请中
                            break;
                        case "03"://注销
                            updateStatus = LetaxStatus.TERMINATED;//终止
                            break;
                        case "02"://注册中
                        case "04"://待审核
                            updateStatus = REGISTERED;//注册中
                            break;
                        default://中心企业驳回和运营端驳回
                            if ("04".equalsIgnoreCase(letaxSnapshot.getRejectType())
                                    || "05".equalsIgnoreCase(letaxSnapshot.getRejectType())) {
                                updateStatus = LetaxStatus.TERMINATED;//终止
                            } else {
                                updateStatus = REGISTER_FAILED;//注册失败
                            }
                            updateRemark = letaxSnapshot.getRejectReason();
                    }
                }

                //终止
                if (updateStatus == LetaxStatus.TERMINATED) {
                    int withdrawCount = letaxWithdrawRepository
                            .count(new UserIdCode(idCode.getValue()),
                                    new AccountId(account.getAccountId().getValue()),
                                    List.of(LetaxWithdrawStatus.APPLIED,
                                            LetaxWithdrawStatus.APPROVED,
                                            LetaxWithdrawStatus.SEND_FAILED,
                                            LetaxWithdrawStatus.ACCOUNT_CHANGED),
                                    REGISTER_SOHO);
                    if (withdrawCount > 0) {
                        throw new BizException(idCode + "用户存在存在提现流程，不可终止,请取消后再操作");
                    }

                    //如果之前的身份为个人，则是升级来的
                    if (serviceInfos.getBeforeIdentity() == PERSON) {
                        //判断个人有没有签约
                        int logCount = signLogRepository.count(new UserIdCode(idCode.getValue()),
                                "sign", PERSON.getVal());

                        if (logCount > 0) {
                            updateHistoryIdentity = null;
                            updateIsSigned = "yes";
                            updateIsView = "NOT_FIRST";
                        } else {
                            updateHistoryIdentity = PERSON;
                            updateIsSigned = "no";
                            updateIsView = "FIRST";
                        }
                        serviceInfos.change(NO_IDENTITY, PERSON, updateHistoryIdentity,
                                updateIsSigned, updateIsView);
                        signRepository.update(serviceInfos.getSignId(), serviceInfos);

                        //启用个人信息最后一条创建的
                        BankCard lastBank = bankCardRepository
                                .findLastOne(new UserIdCode(idCode.getValue()),
                                        BankCardStatus.UNLINK);
                        if (lastBank != null) {
                            lastBank.enable();
                            bankCardRepository.update(lastBank.getBankCardId(), lastBank);
                        }
                    } else {
                        serviceInfos.changeSign2Yes(REGISTER_SOHO, NO_IDENTITY, null, "no");
                        signRepository.update(serviceInfos.getSignId(), serviceInfos);
                    }
                    //插入签约记录表
                    SignLog signLog = new SignLog(
                            new UserIdCode(idCode.getValue()),
                            "终止",
                            REGISTER_SOHO,
                            NO_IDENTITY,
                            "用户自己在app上点击返回操作"
                    );
                    signLogRepository.save(signLog);
                    signRecordRepository.endServiceSignRecord(serviceInfos.getSignId());
                }

                //更新注册信息
                letaxAccount.check();
                LetaxStatus beforeStatus = letaxAccount.getStatus();
                letaxAccount.changeStatus(updateStatus, updateRemark);
                if (LetaxStatus.NEED_AUTH != beforeStatus || LetaxStatus.FINISHED == updateStatus) {
                    letaxRepository.update(letaxAccount.getLetaxAccountId(), letaxAccount);
                }

                //SignRecord signRecord = signRecordRepository.findOrderBy(serviceInfos.getSignId());
                if (serviceInfos.getCurrentIdentity() == REGISTER_SOHO
                        && updateStatus == FINISHED && serviceInfos.getNoticeStatus() == 0) {
                    leTaxOneService.signSuccessToNoticeMember(idCode, letaxAccount.getCheckTime(),
                            serviceInfos);
                }

                //只有初次升级且个体户身份证成功后才能调用java
                if (serviceInfos.getBeforeIdentity() == PERSON
                        && serviceInfos.getCurrentIdentity() == REGISTER_SOHO
                        && updateStatus == FINISHED && letaxAccount.getStatus() != FINISHED) {
                    // 调用java修改收款账户信息
                    try {
                        leTaxOneService.modifyRegisteredWithdrawalRecords(idCode, PERSON);
                    } catch (Exception e) {
                        log.error("modifyRegisteredWithdrawalRecords error", e);
                        return PhpAppResponse.error("系统有点累，请稍后再试");
                    }
                }
            } else {
                return PhpAppResponse.paramError("系统繁忙，请稍后再试");
            }
        }

        return PhpAppResponse.success(true);
    }

    private LetaxSnapshot convert(UserIdCode userIdCode,
                                  LetaxAccountId letaxAccountId,
                                  ServiceLetaxRegisteredReturnResult merchantInfo) {
        if (merchantInfo == null) {
            return null;
        }
        return new LetaxSnapshot(
                null,
                userIdCode,
                merchantInfo.getMerchantId(),
                merchantInfo.getMerchantName(),
                merchantInfo.getMerchantTaxNumber(),
                merchantInfo.getLicenseUrl(),
                merchantInfo.getLicenseCopyUrl(),
                merchantInfo.getName(),
                merchantInfo.getIdCardNo(),
                merchantInfo.getPhoneNumber(),
                merchantInfo.getEmail(),
                merchantInfo.getPoliticalAppearance(),
                merchantInfo.getDegreeEducation(),
                merchantInfo.getStateCode(),
                merchantInfo.getRejectType(),
                merchantInfo.getRejectReason(),
                merchantInfo.getIfFaceAuthenticate(),
                merchantInfo.getOpeningDate(),
                new LetaxAccountId(letaxAccountId.getValue()));
    }

    @Transactional
    public PhpAppResponse<Boolean> updateWithdrawalLog(
            com.tengju.settlement.domain.model.account.UserIdCode idCode,
            WithdrawRequest request) {

        //判断是否存在恶意点击
        if (withdrawService.isUpdateWithdrawalLogClick(
                new com.tengju.bff.domain.shared.UserIdCode(idCode.getValue()))) {
            return PhpAppResponse.paramError("请不要连续操作，10秒后再来！");
        } else {
            withdrawService.updateWithdrawalLogClick(
                    new com.tengju.bff.domain.shared.UserIdCode(idCode.getValue()));
        }
        LetaxWithdrawId letaxWithdrawId = new LetaxWithdrawId(
                Long.parseLong(request.getWithdrawLogId()));

        LetaxWithdraw withdraw = letaxWithdrawRepository.find(letaxWithdrawId);

        if (withdraw == null) {
            return PhpAppResponse.error("提现记录不存在，无法修改");
        }

        //当前身份
        UserIdCode userIdCode = new UserIdCode(idCode.getValue());
        Sign sign = signRepository.find(userIdCode);
        if (sign == null) {
            return PhpAppResponse.error("没有签约，无法修改");
        }
        if (sign.getCurrentIdentity() != REGISTER_SOHO) {
            return PhpAppResponse.error("当前身份不是个体户，不能修改");
        }
        if (sign.getCurrentIdentity() != withdraw.getAuthType()) {
            return PhpAppResponse.error("提现记录身份不是个体户，不能修改");
        }
        IdCardNo idCardNo = new IdCardNo(request.getIdCardNo());
        String idCardName = request.getIdCardName().strip();
        String bankNo = "";
        String bankName = cardBinRepository.getBankName(bankNo);

        Account account = accountRepository.findOrSave(idCode, AccountType.DATA_TREE);

        if (!(bankNo.matches("^\\d+$"))) {
            return PhpAppResponse.paramError("银行卡格式有误，请检查是否包含空格或除数字以外的其它字符");
        }

        // 不同的账号使用不同的身份证 个人收款账户中
        BankCard bankCard = bankCardRepository.find(idCardNo, BankCardStatus.ENABLE);
        if (bankCard != null && bankCard.getIdCode().getValue() != idCode.getValue()) {
            return PhpAppResponse.error(8008, "身份证已被其他个人账号使用，请更换");
        }
        LetaxAccount letaxAccount = letaxRepository
                .findByIdCardNoAndNotStatus(idCardNo, LetaxStatus.TERMINATED);
        if (letaxAccount == null) {
            return PhpAppResponse.error(8008, "没有注册信息");
        }
        if (letaxAccount.getUserIdCode().getValue() != idCode.getValue()) {
            return PhpAppResponse.error(8008, "身份证已关联其他个体户，请更换");
        }
        // 第三方银行卡身份校验
        try {
            userInfoService.checkBankIdCard(idCardName, bankNo, idCardNo.getValue());
        } catch (Exception e) {
            return PhpAppResponse.error(8008, e.getMessage());
        }

        letaxAccount.bindBank(bankNo, bankName);

        letaxRepository.update(letaxAccount.getLetaxAccountId(), letaxAccount);
        BankInfo bankInfo = new BankInfo();
        bankInfo.setBankNo(bankNo);
        bankInfo.setBankName(bankName);
        bankInfo.setIdcardNo(idCardNo.getValue());
        bankInfo.setIdcardName(idCardName);

        //调用java修改收款账户信息
        try {
            leTaxOneService.modifyRegisteredWithdrawalRecords(idCode, withdraw.getAuthType(),
                    letaxWithdrawId, bankInfo);
        } catch (Exception e) {
            log.error("modifyRegisteredWithdrawalRecords error", e);
            return PhpAppResponse.error("系统有点累，请稍后再试");
        }
        return PhpAppResponse.success(true);
    }

    public String h5Login(com.tengju.settlement.domain.model.account.UserIdCode userIdCode) {
        return serviceLetaxRegisteredService.h5Login(((Long) userIdCode.getValue()).intValue());
    }

    public PhpAppResponse<Integer> searchUserStatus(
            com.tengju.settlement.domain.model.account.UserIdCode userIdCode) {
        ServiceLetaxRegisteredReturnResult merchantInfo = serviceLetaxRegisteredService
                .getMerchantInfo((int) userIdCode.getValue());
        if (merchantInfo != null && "Y".equalsIgnoreCase(merchantInfo.getIfFaceAuthenticate())) {
            return PhpAppResponse.success(2);
        } else {
            return PhpAppResponse.success(1);
        }
    }

    public PhpAppResponse<List<IdName>> applyForReason() {
        List<IdName> reasonConfigList = JSON
                .parseArray(ConfigUtil.getConfig().getString("apply.reason", ""), IdName.class);
        return PhpAppResponse.success(reasonConfigList);
    }

    public String addRegisteredCode(
            com.tengju.settlement.domain.model.account.UserIdCode userIdCode) {
        ByteArrayOutputStream os = null;
        ByteArrayInputStream is = null;
        try {
            String lxUrl = serviceLetaxRegisteredService
                    .registeredCode((int) userIdCode.getValue());

            os = new ByteArrayOutputStream();
            generateQRCodeImage(lxUrl, os);
            String filename = userIdCode.toString() + ".png";
            is = parse(os);
            return huaweiObsService.uploadImg(filename, is);
        } catch (Exception e) {
            log.error("addRegisteredCode error", e);
            throw new BizException("注册乐税个体户二维码异常");
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                    log.error("is close error", e);
                }
                try {
                    os.close();
                } catch (Exception e) {
                    log.error("os close error", e);
                }
            }
        }
    }

    public ByteArrayInputStream parse(final OutputStream out) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        baos = (ByteArrayOutputStream) out;
        final ByteArrayInputStream swapStream = new ByteArrayInputStream(baos.toByteArray());
        return swapStream;
    }

    private static void generateQRCodeImage(String text, OutputStream os) throws Exception {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();

        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, 350, 350);

        MatrixToImageWriter.writeToStream(bitMatrix, "PNG", os);
    }

    public String getArticleInfo(String id) {
        String content = "";
        if (StringUtils.isBlank(id)) {
            throw new BizException("参数异常");
        }
        content = articleInfoRepository
                .getArticleInfoContent(Integer.valueOf(id));
        if (StringUtils.isNotBlank(content)) {
            content = content.replace("<p>", "\n");
        }
        return content;
    }


    public PhpAppResponse<ApplyPopupVO> applyPopup(com.tengju.settlement.domain.model.account.UserIdCode userIdCode) {
        Sign serviceInfos = signRepository.find(new UserIdCode(userIdCode.getValue()));
        if (serviceInfos == null) {
            return PhpAppResponse.paramError("请求失败，该商户没有进行签约");
        }
        ApplyPopupVO vo = new ApplyPopupVO();
        vo.setCanApply(true);
        Map<String, String> serviceFeeApplyPopupMap = JsonUtil.toMap(serviceFeeApplyPopupMapString);
        List<String> identityVal = Lists.newArrayList(StringUtils.split(serviceFeeApplyPopupMap.get("identity"), ","));
        if (identityVal.contains(serviceInfos.getCurrentIdentity().getVal())) {
            String canApply = serviceFeeApplyPopupMap.get("canApply");
            String title = serviceFeeApplyPopupMap.get("title");
            String desc = serviceFeeApplyPopupMap.get("desc");
            String url = serviceFeeApplyPopupMap.get("url");
            vo.setCanApply(Boolean.parseBoolean(canApply));
            vo.setTitle(title);
            vo.setDesc(desc);
            vo.setUrl(url);
        }

        return PhpAppResponse.success(vo);
    }
}
